<template>
  <span
    :class="classes"
    :style="styles"
  >
    <img
      v-if="src"
      :src="src"
      @error="handleError"
    >
    <Icon
      v-else-if="icon || customIcon"
      :type="icon"
      :custom="customIcon"
    />
    <span
      v-else
      ref="children"
      :class="[prefixCls + '-string']"
      :style="childrenStyle"
    ><slot /></span>
  </span>
</template>
<script>
import Icon from './icon'
import { oneOf } from '../utils/assist'

const prefixCls = 'ivu-avatar'

const sizeList = ['small', 'large', 'default']

export default {
  name: 'Avatar',
  components: { Icon },
  props: {
    shape: {
      validator (value) {
        return oneOf(value, ['circle', 'square'])
      },
      default: 'circle'
    },
    size: {
      type: [String, Number],
      default () {
        return 'default'
      }
    },
    src: {
      type: String
    },
    icon: {
      type: String
    },
    customIcon: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      prefixCls: prefixCls,
      scale: 1,
      childrenWidth: 0,
      isSlotShow: false,
      slotTemp: null
    }
  },
  computed: {
    classes () {
      return [
                    `${prefixCls}`,
                    `${prefixCls}-${this.shape}`,
                    {
                      [`${prefixCls}-image`]: !!this.src,
                      [`${prefixCls}-icon`]: !!this.icon || !!this.customIcon,
                      [`${prefixCls}-${this.size}`]: oneOf(this.size, sizeList)
                    }
      ]
    },
    styles () {
      const style = {}
      if (this.size && !oneOf(this.size, sizeList)) {
        style.width = `${this.size}px`
        style.height = `${this.size}px`
        style.lineHeight = `${this.size}px`
        style.fontSize = `${this.size / 2}px`
      }
      return style
    },
    childrenStyle () {
      let style = {}
      if (this.isSlotShow) {
        style = {
          msTransform: `scale(${this.scale})`,
          WebkitTransform: `scale(${this.scale})`,
          transform: `scale(${this.scale})`,
          position: 'absolute',
          display: 'inline-block',
          left: `calc(50% - ${Math.round(this.childrenWidth / 2)}px)`
        }
      }
      return style
    }
  },
  watch: {
    size (val, oldVal) {
      if (val !== oldVal) this.setScale()
    }
  },
  beforeCreate () {
    this.slotTemp = this.$slots.default
  },
  mounted () {
    this.setScale()
  },
  updated () {
    if (this.$slots.default !== this.slotTemp) {
      this.slotTemp = this.$slots.default
      this.setScale()
    }
  },
  methods: {
    setScale () {
      this.isSlotShow = !this.src && !this.icon
      if (this.$refs.children) {
        // set children width again to make slot centered
        this.childrenWidth = this.$refs.children.offsetWidth
        const avatarWidth = this.$el.getBoundingClientRect().width
        // add 4px gap for each side to get better performance
        if (avatarWidth - 8 < this.childrenWidth) {
          this.scale = (avatarWidth - 8) / this.childrenWidth
        } else {
          this.scale = 1
        }
      }
    },
    handleError (e) {
      this.$emit('on-error', e)
    }
  }
}
</script>
